using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Xml;

using ExifLibrary;
using Nini.Ini;

namespace NameTagTranslator
{
	class MainClass
	{
		public static void Main (string[] args)
		{
			if (args.Length != 2) {
				Console.WriteLine("usage: NameTagTranslator <photo directory> <Contacts.xml path>");
				return;
			}
			
			Console.WriteLine("args: " + String.Join(", ", args));
			DirectoryInfo dirInfo = new DirectoryInfo(args[0]);
			if (!dirInfo.Exists) {
				Console.WriteLine("photo directory (" + args[0] + ") does not exist");
				return;
			}
			
			Dictionary<String, String> idNames = RetrieveNames_(args[1]);
			Console.WriteLine("Found " + idNames.Count + " names in contacts file.");

			String directory = args[0];
			Dictionary<String, List<String>> photoNames = GetNameTags_(directory);
			Console.WriteLine("Found " + photoNames.Count + " photos with name tags.");
			if (photoNames.Count <= 0)
				return;
			
			Dictionary<String, DateTime> photoTimes = GetExifTimes_(directory, photoNames.Keys.ToList());
			Console.WriteLine("Found " + photoTimes.Count + " times from EXIF info.");
			if (photoTimes.Count <= 0)
				return;
			
			// TODO: merge names and times
			DateTime minDate = DateTime.MaxValue, maxDate = DateTime.MinValue;
			foreach (DateTime time in photoTimes.Values) {
				if (DateTime.Compare(time, minDate) < 0)
					minDate = time;
				if (DateTime.Compare(time, maxDate) > 0)
					maxDate = time;
			}
			Console.WriteLine("Times range from " + minDate.ToString() + " to " + maxDate.ToString());
		}
		
		
		static Dictionary<String, List<String>> GetNameTags_(String directory)
		{
			Dictionary<String, List<String>> photoNames = new Dictionary<string, List<string>>(); 
			IniDocument doc = new IniDocument(directory + "/" + ".picasa.ini");
			foreach (DictionaryEntry entry in doc.Sections) {
				if (!(entry.Value is IniSection))
					continue;
				IniSection section = (IniSection)entry.Value;
				if (!section.Contains("faces"))
					continue;

				List<String> faceIds = new List<String>();
				String[] rectNameStrings = section.GetValue("faces").Split(';');
				foreach (String rectName in rectNameStrings) {
					String[] tokens = rectName.Split(',');
					if (tokens.Length == 2 && tokens[1] != "ffffffffffffffff")
						faceIds.Add(tokens[1]);
				}

				if (faceIds.Count > 0)
					photoNames[section.Name] = faceIds;
			}
			return photoNames;
		}

		
		static Dictionary<String, DateTime> GetExifTimes_(String directory, List<String> fileNames)
		{
			Dictionary<String, DateTime> photoTimes = new Dictionary<String, DateTime>();
			foreach (String fileName in fileNames) {
				String path = directory + "/" + fileName;
				ExifFile exifFile = ExifFile.Read(path);
				if (!exifFile.Properties.ContainsKey(ExifTag.DateTimeOriginal))
					continue;
				ExifProperty exifProp = exifFile.Properties[ExifTag.DateTimeOriginal];
				if (!(exifProp is ExifDateTime))
					continue;
				photoTimes[fileName] = (exifProp as ExifDateTime).Value;
			}
			return photoTimes;
		}
		
		
		static Dictionary<String, String> RetrieveNames_(String contactsFilePath)
		{
			Dictionary<String, String> idNames = new Dictionary<String, String>();
			XmlDocument doc = new XmlDocument();
			doc.Load(contactsFilePath);
			XmlNodeList contactNodes = doc.GetElementsByTagName("contact");
			foreach (XmlNode contactNode in contactNodes) {
				String id = contactNode.Attributes["id"].Value;
				String name = contactNode.Attributes["name"].Value;
				idNames[id] = name;
			}
			return idNames;
		}
	}
}

			                      
			                      
			                      
			                      
			                      
			                      
